package gsc.org.tokenizer;

import java.util.ArrayList;
import java.util.List;

/**
 * Created with IntelliJ IDEA.
 * User: gianluca
 * Date: 02/04/13
 * Time: 16.35
 * To change this template use File | Settings | File Templates.
 */
public class MyTokenizer {
    private final String str;
    private ArrayList<String> separators = new ArrayList<String>();

    public MyTokenizer(String str) {
        this.str = str;
        separators.add("\n");
        separators.add("\r");
        separators.add(" ");
        separators.add("(");
        separators.add(")");
        separators.add("[");
        separators.add("]");
        separators.add("{");
        separators.add("}");
        separators.add("*");
        separators.add(",");
        separators.add(";");
        separators.add("=");


        separators.add("//");

    }

    public void addSeparator(String separator) {
        this.separators.add(separator);
    }

    public List<Token> getTokens() {
        ArrayList<Token> tokens = extractTokens();
        return tokens;  //To change body of created methods use File | Settings | File Templates.
    }

    private boolean isNewLine(char c) {
        if ((c == '\n') || (c == '\r')) {
            return true;
        }
        return false;
    }

    private ArrayList<Token> extractTokens() {
        ArrayList<Token> tokens = new ArrayList<Token>();
        char[] arr = this.str.toCharArray();
        StringBuffer buffer = new StringBuffer();
        int lineNumber = 1;
        int beginLineNumber = 0;
        boolean beginLineComent = false;
        boolean beginBlockComment = false;

        for (int i = 0; i < arr.length; i++) {
            char cCurrent = arr[i];
            //Look Forward
            char cNext = 0;

            if (i < arr.length - 1) {
                cNext = arr[i + 1];
            }

            if (beginLineComent && !isNewLine(cCurrent)) {
                //Skil character
                continue;
            }

            if (isNewLine(cCurrent)) {
                lineNumber++;

                //Reset beginLineComment
                beginLineComent = false;

                continue;
            } else {
                if (cCurrent == '/' && cNext == '/') {
                    // Remove comment but increase lineNumber
                    beginLineComent = true;
                    continue;
                } else if (cCurrent == '/' && cNext == '*') {
                    // begin block comment
                    beginBlockComment = true;
                    continue;
                }
            }
            String s = Character.toString(cCurrent);
            if (separators.contains(s)) {
                if (buffer.length() > 0) {
                    String str = buffer.toString();
                    Integer strI = null;
                    boolean isInteger = false;
                    try {
                        strI = Integer.parseInt(str);
                        isInteger = true;
                    } catch (NumberFormatException e) {
                    }
                    Token t;
                    if (!isInteger) {
                        t = new Token(TokenType.STANDARD, str, beginLineNumber);
                    } else {
                        t = new Token(TokenType.NUMBER, strI, beginLineNumber);
                    }

                    tokens.add(t);
                    //TODO non mi piace
                    buffer = new StringBuffer();
                }
                if (cCurrent != ' ') {
                    Token token = new Token(TokenType.SEPARATOR, s, lineNumber);
                    tokens.add(token);
                }

            } else {
                if (buffer.length() == 0) {
                    beginLineNumber = lineNumber;
                }
                buffer.append(cCurrent);
            }
        }
        if (buffer.length() > 0) {
            Token t = new Token(TokenType.STANDARD, buffer.toString(), lineNumber);
            tokens.add(t);
        }
        return tokens;
    }
}
